home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 29 / develop issue 29 code / qd3d viewer code / fullfeatured3dapp / fullfeatured3dapp.c next >
Encoding:
C/C++ Source or Header  |  1996-08-22  |  43.6 KB  |  1,757 lines

  1. /*
  2. **    This is a viewer application shell
  3. **
  4. **    Nick Thompson, 1/31/96
  5. */
  6.  
  7.  
  8. /*------------------------------------------------------------*/
  9.  
  10. /* always include this before anything else when using the QuickDraw 3D viewer */
  11. #include "QD3D.h"
  12.  
  13. /* all we need is this header - to use the viewer */
  14. #include "QD3DViewer.h"
  15.  
  16. /* this has the routines for renderer objects */
  17. #include "QD3DRenderer.h"
  18.  
  19. /* this has the routines for view objects */
  20. #include "QD3DView.h"
  21.  
  22. /* this header allows us to check for the viewer */
  23. #include <CodeFragments.h>
  24.  
  25. #include <QuickDraw.h>
  26. #include <ColorPicker.h>
  27. /*------------------------------------------------------------*/
  28.  
  29. /* convenience macros to peek at event records */
  30.  
  31. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  32. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  33.  
  34.  
  35. /*------------------------------------------------------------*/
  36.  
  37. /* function prototypes for the application */
  38.  
  39. void            LoadMenuBarForApplication( short myMenuBarID ) ;
  40. void             FatalAlert( short theErrorMessage ) ;
  41. void            InitializeToolBox( void ) ;
  42. Boolean         HasQuickDraw3DViewer( void ) ;
  43. Boolean         SupportsAEVT( void ) ;
  44. void             RegisterRequiredAppleEventHandlers( void ) ;
  45.  
  46. pascal OSErr     HandleCoreAppleEventOfTypeOAPP(    AppleEvent *theAppleEvent, 
  47.                                 AppleEvent *theAppleEventReply, 
  48.                                 long userDefinedReferenceConstant) ;
  49.                                 
  50. pascal OSErr     HandleCoreAppleEventOfTypeODOC( AppleEvent *theAppleEvent, 
  51.                                 AppleEvent *theAppleEventReply, 
  52.                                 long userDefinedReferenceConstant) ;
  53.                                 
  54. pascal OSErr     HandleCoreAppleEventOfTypePDOC( AppleEvent *theAppleEvent, 
  55.                                 AppleEvent *theAppleEventReply,
  56.                                 long userDefinedReferenceConstant) ;
  57.                                 
  58. pascal OSErr     HandleCoreAppleEventOfTypeQUIT( AppleEvent *theAppleEvent, 
  59.                                 AppleEvent *theAppleEventReply,
  60.                                 long userDefinedReferenceConstant) ; 
  61.                                 
  62. void            MainEventLoop( void ) ; 
  63.  
  64. void             HandleKeyPress(EventRecord *theEventRecord) ;
  65. void             HandleMenuCommand(long menuResult) ;
  66. void             HandleAppleMenu( short menuItem ) ;
  67. void             HandleFileMenu( short menuItem ) ;
  68. WindowPtr         HandleFileNewItem( unsigned char *windowTitle ) ;
  69. OSErr             HandleFileSaveAsItem( WindowPtr theWindow ) ;
  70. OSErr             HandleFileSaveItem( WindowPtr theWindow ) ;
  71. OSErr             HandleFileRevertItem( WindowPtr theWindow ) ;
  72. OSErr             HandleFilePageSetupItem( WindowPtr theWindow ) ;
  73. OSErr             HandleFilePrintItem( WindowPtr theWindow ) ;
  74. WindowPtr         HandleFileOpenItem( FSSpec *theFSSpec ) ;
  75. OSErr             HandleFileCloseItem( WindowPtr theWindow ) ;
  76. OSErr             HandleFileQuitItem( void ) ;
  77. void             HandleEditMenu( short menuItem ) ;
  78. void             HandleRendererMenu( short menuItem ) ;
  79. void             HandleViewMenu( short menuItem ) ;
  80.  
  81. WindowPtr         DoCreateNewViewerWindow( unsigned char *windowName ) ;
  82. Boolean         PickViewerBackGroundColor(RGBColor *theRGBColor, unsigned char *thePrompt ) ;
  83. void             AdjustMenus( void ) ;
  84. /*------------------------------------------------------------*/
  85.  
  86. /* constants */
  87. const    short                kWindHeight = 250 ;            /* default theWindow height */
  88. const    short                kWindWidth = 200 ;            /* default theWindow width */
  89. const    SFTypeList            kTypeList = { '3DMF' } ;    /* file type we can open */
  90. const    short                kNumTypes = 1 ;             /* num of file types we can recognise */
  91.  
  92. const    short                kAppMenuBarID = 128 ;        /* resource ID for the application's menu bar */
  93. const    short                kFatalAlert = 128 ;            /* res ID for error alert before we bail */
  94. const    short                 kErrorAlertStrings = 128 ;    /* res ID for alert strs */
  95. const    short                kAboutDialogID = 129;        /* ID for the about box dialog */
  96.  
  97. const    short                kInsetPixelsConst = 12 ;    /* num of pixels to inset view by */
  98. /* error codes */
  99. enum {
  100.     kNoMenuBar = 1,
  101.     kNoQD3DViewerLib,
  102.     kNoAEVTSupport
  103. } ;
  104.  
  105. /* menu resource IDs */
  106. enum {
  107.     mRendererMenu = 1,    /* hierarchical, stored in the view menu */
  108.     mAppleMenu = 128,
  109.     mFileMenu,
  110.     mEditMenu,
  111.     mViewMenu
  112. } ;
  113.  
  114. /* item numbers - Apple menu */
  115. enum {
  116.     iAppleAboutItem = 1
  117. } ;
  118.  
  119. /* item numbers - File menu */
  120. enum {
  121.     iFileNewItem = 1,
  122.     iFileOpenItem,
  123.     iFileCloseItem = 4,
  124.     iFileSaveItem,
  125.     iFileSaveAsItem,
  126.     iFileRevertItem,
  127.     iFilePageSetupItem = 9,
  128.     iFilePrintItem,
  129.     iFileQuitItem = 12
  130. } ;
  131.  
  132. /* item numbers - Edit menu */
  133. enum {
  134.     iEditUndoItem = 1,
  135.     iEditCutItem = 3,
  136.     iEditCopyItem,
  137.     iEditPasteItem,
  138.     iEditClearItem = 7
  139. } ;
  140.  
  141. /* item numbers - View menu */
  142. enum {
  143.     iViewRendererItem = 1,
  144.     iViewBadgeItem = 3,
  145.     iViewCameraButtonItem = 5,
  146.     iViewTruckButtonItem,
  147.     iViewOrbitButtonItem,
  148.     iViewZoomButtonItem,
  149.     iViewDollyButtonItem,
  150.     iViewInsetNFrameItem = 11,
  151.     iViewSetBackgroundColorItem
  152. } ;
  153.  
  154. /* item numbers - Renderer hierarchical menu */
  155. enum {
  156.     iRendererInteractiveItem = 1,
  157.     iRendererWireframeItem
  158. } ;
  159.  
  160.  
  161. /*------------------------------------------------------------*/
  162.  
  163. /* type definitions */
  164.  
  165. typedef struct {
  166.  
  167.     TQ3ViewerObject        fViewer ;        /* stores reference to the viewer object */
  168.     FSSpec                fFSSpec    ;        /* reference to the file for the document */
  169.     
  170. } ViewerDocument, *ViewerDocumentPtr, **ViewerDocumentHdl ;
  171.  
  172. /*------------------------------------------------------------*/
  173.  
  174. /* global variables */
  175. Boolean                gQuitFlag = false ;    /* set to true to quit application */
  176. AEAddressDesc        gSelfAddress;        /* A self-addressed address descriptor record */
  177.  
  178. /*------------------------------------------------------------*/
  179.  
  180.  
  181. void main(void)
  182. {
  183.     InitializeToolBox() ;
  184.     LoadMenuBarForApplication( kAppMenuBarID ) ;
  185.     
  186.     /*
  187.     ** check that we have AppleEvents, and if so install the
  188.     ** AppleEvent handlers for the required AppleEvents
  189.     */
  190.     
  191.     if( SupportsAEVT() ) 
  192.     {
  193.         RegisterRequiredAppleEventHandlers() ;
  194.         
  195.         /*
  196.         ** Check that the viewer is installed
  197.         */
  198.         if( HasQuickDraw3DViewer() )
  199.         {
  200.             MainEventLoop() ;
  201.         }
  202.     }
  203.  
  204.     ExitToShell();    
  205.     
  206. }
  207.  
  208.  
  209. /*------------------------------------------------------------*/
  210.  
  211. /*
  212. ** Load the menu bar specified.
  213. */
  214.  
  215. void LoadMenuBarForApplication( short myMenuBarID )
  216. {
  217.     Handle        menuBar = NULL;
  218.  
  219.     /* 
  220.     **Read menus into menu bar specified by the resource 
  221.     ** id passed into this routine by myMenuBarID 
  222.     */
  223.     menuBar = GetNewMBar(myMenuBarID);    
  224.     
  225.     if ( menuBar == NULL )
  226.          ExitToShell();
  227.          
  228.     /* Install the menus we just read in */              
  229.     SetMenuBar(menuBar);
  230.     
  231.     /* it is now safe to dispose the menu handle */
  232.     DisposeHandle(menuBar);
  233.     
  234.     /* 
  235.     ** this next routine adds the names of desk accessories 
  236.     ** to the specified menu, in this case the apple menu
  237.     */
  238.     AppendResMenu( GetMenuHandle( mAppleMenu ), 'DRVR' );
  239.     
  240.     /*
  241.     ** now add the two hierarchical menus, one to 
  242.     ** select the renderer and one to select the 
  243.     ** the type of camera we are using
  244.     */
  245.     InsertMenu(GetMenu( mRendererMenu ), -1);
  246.  
  247.     /* call our routine to grey out menus as appropriate */
  248.     AdjustMenus() ;
  249.     
  250.     /* finally ensure the new menubar gets drawn */
  251.     DrawMenuBar();
  252. }
  253.  
  254.  
  255.  
  256. /*------------------------------------------------------------*/
  257.  
  258. /*
  259. ** Display an alert and quit.
  260. */
  261.  
  262. void FatalAlert( short theErrorMessage )
  263. {
  264.     unsigned char    *thePString, theErrorStr[256] ;
  265.     
  266.     thePString = theErrorStr ;
  267.     
  268.     GetIndString( thePString, kErrorAlertStrings, theErrorMessage ) ;
  269.     ParamText( thePString, "\p", "\p", "\p" ) ;
  270.     StopAlert( kFatalAlert, NULL ) ;
  271.     ExitToShell() ;
  272. }
  273.  
  274. /*------------------------------------------------------------*/
  275.  
  276. /*
  277. ** Initialize all the needed managers.
  278. */
  279.  
  280. void     InitializeToolBox( void )
  281. {
  282.     /*
  283.     ** Initialize the toolbox managers
  284.     */
  285.     InitGraf((Ptr)&qd.thePort);
  286.     InitFonts();
  287.     InitWindows();
  288.     InitMenus();
  289.     TEInit();
  290.     InitDialogs((long)NULL);
  291.     InitCursor();
  292.  
  293.     /*
  294.     ** must call this so that the heap is expanded to maximum
  295.     ** size before calling any viewer routines
  296.     */
  297.     MaxApplZone() ;
  298.     
  299. }
  300.  
  301. /*------------------------------------------------------------*/
  302.  
  303. /*
  304. ** return true if the viewer is installed
  305. */
  306.  
  307. Boolean     HasQuickDraw3DViewer( void )
  308. {
  309.     return((long) Q3ViewerNew != kUnresolvedCFragSymbolAddress) ;
  310. }
  311.  
  312. /*------------------------------------------------------------*/
  313.  
  314. /*
  315. ** returns true if the platform supports appleevents - we won't run
  316. ** if it doesn't
  317. */
  318. Boolean SupportsAEVT(void)
  319. {
  320.     OSErr theError;
  321.     long response;
  322.         
  323.     theError = Gestalt(gestaltAppleEventsAttr,&response);
  324.     if (theError!=noErr)
  325.         return false;
  326.         
  327.     return (response && (response << gestaltAppleEventsPresent));
  328. }
  329.  
  330. /*------------------------------------------------------------*/
  331.  
  332. /*
  333. ** called to register our AppleEvent handlers.
  334. **
  335. ** Should really have some error handling in here.
  336. */
  337. void RegisterRequiredAppleEventHandlers(void)
  338. {
  339.     OSErr                 theError;
  340.     ProcessSerialNumber    myApplicationPSN;            /* This application's psn */
  341.     
  342.     /* Set up a self-addressed descriptor record. */
  343.      myApplicationPSN.highLongOfPSN = 0;
  344.      myApplicationPSN.lowLongOfPSN = kCurrentProcess ;
  345.      
  346.      theError = AECreateDesc(typeProcessSerialNumber,
  347.                              (Ptr)&myApplicationPSN,
  348.                              sizeof(ProcessSerialNumber),
  349.                              &gSelfAddress);
  350.     if (theError!=noErr)
  351.         return;
  352.     
  353.     theError = AEInstallEventHandler(    kCoreEventClass,
  354.                                         kAEOpenApplication,
  355.                                         NewAEEventHandlerProc(HandleCoreAppleEventOfTypeOAPP),
  356.                                         0L,
  357.                                         false);
  358.     if (theError!=noErr)
  359.         return;
  360.                 
  361.     theError = AEInstallEventHandler(    kCoreEventClass,
  362.                                         kAEOpenDocuments,
  363.                                         NewAEEventHandlerProc(HandleCoreAppleEventOfTypeODOC),
  364.                                         0L,
  365.                                         false);
  366.     if (theError!=noErr)
  367.         return;
  368.                 
  369.     theError = AEInstallEventHandler(    kCoreEventClass,
  370.                                         kAEPrintDocuments,
  371.                                         NewAEEventHandlerProc(HandleCoreAppleEventOfTypePDOC),
  372.                                         0L,
  373.                                         false);
  374.     if (theError!=noErr)
  375.         return;
  376.                 
  377.     theError = AEInstallEventHandler(    kCoreEventClass,
  378.                                         kAEQuitApplication,
  379.                                         NewAEEventHandlerProc(HandleCoreAppleEventOfTypeQUIT),
  380.                                         0L,
  381.                                         false);
  382.     if (theError!=noErr)
  383.         return;
  384. }
  385.  
  386.  
  387. /*------------------------------------------------------------*/
  388.  
  389. /*
  390. ** open application theEventRecord handler for the core theEventRecord suite, 
  391. ** by default we just want a blank new document
  392. */
  393. pascal OSErr HandleCoreAppleEventOfTypeOAPP( AppleEvent *theAppleEvent, AppleEvent *theAppleEventReply, long userDefinedReferenceConstant)
  394. {
  395.     /*
  396.     ** we don't actually do anything on open - you could,
  397.     ** for example you might want to open a blank untitled 
  398.     ** theWindow
  399.     */
  400.     OSErr theError = noErr ;
  401.     return theError;
  402. }
  403.  
  404.  
  405. /*------------------------------------------------------------*/
  406.  
  407. /*
  408. ** handler for the open document AppleEvent handler
  409. */
  410.  
  411. pascal OSErr HandleCoreAppleEventOfTypeODOC(AppleEvent *theAppleEvent, AppleEvent *theAppleEventReply, long userDefinedReferenceConstant)
  412. {
  413.     FSSpec         theFileSpec;
  414.     AEDescList    theDocumentList;
  415.     OSErr        theError,
  416.                 theIgnoredError;
  417.     long        myTempIndex,
  418.                 numberOfItemsInList;
  419.     Size         actualSize;
  420.     AEKeyword    theAEKeyword;
  421.     DescType    theDescriptorType;
  422.  
  423.     
  424.     theError = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&theDocumentList);
  425.     if (theError == noErr) {
  426.         /*
  427.         ** see how many descriptor items are in the list
  428.         ** this is the number of documents we want to open
  429.         */
  430.         theError = AECountItems(&theDocumentList,&numberOfItemsInList);
  431.         
  432.         /*
  433.         ** now get each descriptor record from the list
  434.         ** coerce the returned data to an FSSpec record, and
  435.         ** open the asoociated file
  436.         */
  437.         for (myTempIndex=1; myTempIndex <= numberOfItemsInList && theError == noErr; myTempIndex++) {
  438.         
  439.             theError = AEGetNthPtr(    &theDocumentList, 
  440.                                     myTempIndex,
  441.                                     typeFSS,
  442.                                     &theAEKeyword,
  443.                                     &theDescriptorType,
  444.                                     (Ptr)&theFileSpec,
  445.                                     sizeof(theFileSpec),
  446.                                     &actualSize);
  447.     
  448.             if (theError == noErr)    {
  449.             
  450.                 FInfo        fndrInfo ;
  451.                 
  452.                 /*
  453.                 ** we now have a valid FSSpec to reference the file, we need to know 
  454.                 ** what type the file is to determine which file open function to call
  455.                 ** we can determine this from the finder info for the file
  456.                 */
  457.                 
  458.                 theError = FSpGetFInfo( &theFileSpec, &fndrInfo );    
  459.                 
  460.                 /*
  461.                 ** if we got that ok, then we switch on the file  
  462.                 ** type (we don't care about the creator type)    
  463.                 */
  464.                         
  465.                 if (theError == noErr)    {
  466.                 
  467.                     switch( fndrInfo.fdType ) {
  468.                         case '3DMF':
  469.                             HandleFileOpenItem( &theFileSpec );
  470.                             break ;
  471.                     }
  472.                 }
  473.             }
  474.         }
  475.         theIgnoredError = AEDisposeDesc(&theDocumentList);
  476.     }
  477.     return theError ;
  478. }
  479.  
  480. /*------------------------------------------------------------*/
  481.  
  482. /*
  483. ** handler for the print document theEventRecord handler
  484. */
  485. pascal OSErr HandleCoreAppleEventOfTypePDOC(AppleEvent *theAppleEvent,AppleEvent *theAppleEventReply,long userDefinedReferenceConstant)
  486. {
  487.     FSSpec         theFileSpec;
  488.     AEDescList    theDocumentList;
  489.     OSErr        theError;
  490.     long        myTempIndex,
  491.                 numberOfItemsInList;
  492.     Size         actualSize;
  493.     AEKeyword    theAEKeyword;
  494.     DescType    theDescriptorType;
  495.  
  496.     
  497.     theError = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&theDocumentList);
  498.     if (theError == noErr) {    
  499.         
  500.         /*
  501.         ** see how many descriptor items are in the list
  502.         ** this is the number of documents we want to print
  503.         */
  504.         
  505.         theError = AECountItems(&theDocumentList,&numberOfItemsInList);
  506.  
  507.         /*
  508.         ** now get each descriptor record from the list
  509.         ** coerce the returned data to an FSSpec record, and
  510.         ** print the asoociated file
  511.         */
  512.         
  513.         for (myTempIndex=1; myTempIndex <= numberOfItemsInList && theError == noErr; myTempIndex++) {
  514.         
  515.             theError = AEGetNthPtr(    &theDocumentList, 
  516.                                 myTempIndex,
  517.                                 typeFSS,
  518.                                 &theAEKeyword,
  519.                                 &theDescriptorType,
  520.                                 (Ptr)&theFileSpec,
  521.                                 sizeof(theFileSpec),
  522.                                 &actualSize);
  523.     
  524.             if (theError == noErr)    {    
  525.                             
  526.                 /*
  527.                 ** if the app handles printing then you could do 
  528.                 ** something like: theError = HandlePrintDoc( &theFileSpec );
  529.                 */
  530.                 
  531.                 theError = errAEEventNotHandled ;
  532.             }
  533.         }
  534.         theError = AEDisposeDesc(&theDocumentList);
  535.     }
  536.     return theError ;
  537. }
  538.  
  539. /*------------------------------------------------------------*/
  540.  
  541. /*
  542. ** Quit AppleEvent handler
  543. */
  544.  
  545. pascal OSErr HandleCoreAppleEventOfTypeQUIT(AppleEvent *theAppleEvent,AppleEvent *theAppleEventReply,long userDefinedReferenceConstant)
  546. {
  547.     OSErr             theError = noErr ;        /* this is used as the return value */
  548.  
  549.     theError = HandleFileQuitItem() ;
  550.             
  551.     return theError ;
  552. }
  553.  
  554. /*------------------------------------------------------------*/
  555.  
  556. /*
  557. ** we want to handle events until the fronmost theWindow goes away
  558. */
  559.  
  560. void MainEventLoop( void )
  561. {
  562.     EventRecord     theEventRecord;
  563.     WindowPtr       theWindow;
  564.     short           thePart;
  565.     Rect            screenRect;
  566.     Point            aPoint = {100, 100};
  567.     GrafPtr            oldPort ;
  568.     Boolean            wasViewerEvent ;
  569.     TQ3ViewerObject    theViewer ;
  570.  
  571.     
  572.  
  573.     while( !gQuitFlag )
  574.     {
  575.         Point            mouseLoc ;
  576.         
  577.         if (WaitNextEvent( everyEvent, &theEventRecord,  GetCaretTime(), NULL ))
  578.         {
  579.  
  580.             AdjustMenus() ;
  581.  
  582.               /*
  583.               ** There is a bug in versions 1.0.4 and earlier of the Viewer,
  584.               ** so the port has to be set and restored.
  585.               */
  586.               if(( theWindow = FrontWindow()) != NULL)
  587.               {
  588.                 ViewerDocumentHdl    theViewerDocumentHdl ;
  589.                 TQ3ViewerObject        theViewer ;
  590.                 
  591.                 theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  592.                 if(theViewerDocumentHdl != NULL) 
  593.                 {
  594.                     if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  595.                     {
  596.                         GetPort( &oldPort ) ;
  597.                         SetPort((GrafPtr)theWindow ) ;
  598.         
  599.                         wasViewerEvent = Q3ViewerEvent( theViewer, &theEventRecord );
  600.                         GetMouse( &mouseLoc ) ;
  601.                         Q3ViewerAdjustCursor( theViewer,  &mouseLoc );
  602.                         SetPort( oldPort ) ;
  603.                     }
  604.                 }
  605.                 
  606.             }
  607.             else
  608.             {
  609.                 wasViewerEvent = false ;
  610.             }
  611.             
  612.             if( !wasViewerEvent )
  613.             {
  614.                 SetCursor( &qd.arrow ) ;
  615.                 switch (theEventRecord.what) 
  616.                 {
  617.                     case mouseDown:
  618.                     
  619.                         thePart = FindWindow( theEventRecord.where, &theWindow );
  620.                         
  621.                         switch( thePart ) {
  622.                             case inMenuBar: 
  623.                                 HandleMenuCommand(MenuSelect(theEventRecord.where));
  624.                                 break;
  625.                             
  626.                             case inDrag:
  627.                         
  628.                                 screenRect = (**GetGrayRgn()).rgnBBox;
  629.                                 DragWindow( theWindow, theEventRecord.where, &screenRect );
  630.                                 break ;
  631.                         
  632.                             case inContent:
  633.                         
  634.                                 if (theWindow != FrontWindow())
  635.                                     SelectWindow( theWindow );
  636.                                 break ;
  637.                         
  638.                             case inGoAway:
  639.                                 if (TrackGoAway( theWindow, theEventRecord.where )) {
  640.                                     DisposeWindow ( theWindow );
  641.                                 }
  642.                                 break ;
  643.                                 
  644.                             default:
  645.                                 break ;
  646.                         }
  647.                         break ;
  648.                                 
  649.                             
  650.                     case updateEvt:
  651.     
  652.                         theWindow = (WindowPtr)theEventRecord.message;
  653.                         GetPort(&oldPort ) ;    
  654.                         SetPort( theWindow );
  655.                         
  656.                         BeginUpdate( theWindow );
  657.                         {
  658.                             TQ3ViewerObject        theViewer ;
  659.                             OSErr                theErr ;
  660.                             ViewerDocumentHdl    theViewerDocumentHdl ;
  661.  
  662.                             theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  663.                             if(theViewerDocumentHdl != NULL) 
  664.                             {
  665.                                 if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  666.                                 {
  667.                                     theErr = Q3ViewerDraw( theViewer );
  668.                                 }
  669.                             }
  670.                         }
  671.                         EndUpdate( theWindow );
  672.                         SetPort( oldPort ) ;
  673.                         break ;
  674.                         
  675.                     case keyDown:
  676.                     case autoKey:
  677.                         HandleKeyPress(&theEventRecord);
  678.                         break;
  679.                         
  680.                     case diskEvt:
  681.                         if ( HiWrd(theEventRecord.message) != noErr ) 
  682.                             (void) DIBadMount(aPoint, theEventRecord.message);
  683.                         break;
  684.                         
  685.                     case osEvt:
  686.                     case activateEvt:
  687.                         break;
  688.  
  689.                 }
  690.             }
  691.         }
  692.     }
  693. }
  694.  
  695.  
  696. /*------------------------------------------------------------*/
  697.  
  698. /*
  699. ** handle keydow events, all we do is dispatch to the 
  700. ** menu handler if the command key is down, otherwise
  701. ** the keypress is ignored.
  702. */
  703.  
  704. void HandleKeyPress(EventRecord *theEventRecord)
  705. {
  706.     char    key;
  707.  
  708.     key = theEventRecord->message & charCodeMask;
  709.     
  710.     /* check to see if we selected a menu */
  711.     if ( theEventRecord->modifiers & cmdKey ) {        /* Command key down? */
  712.         HandleMenuCommand(MenuKey(key));
  713.     } 
  714. }
  715.  
  716.  
  717. /*------------------------------------------------------------*/
  718.  
  719. /*
  720. ** handle menu commands
  721. */
  722.  
  723. void HandleMenuCommand(long menuResult)
  724. {
  725.     short        menuID;
  726.     short        menuItem;
  727.  
  728.     menuID = HiWrd(menuResult);
  729.     menuItem = LoWrd(menuResult);
  730.  
  731.     switch ( menuID ) {
  732.     
  733.         case mRendererMenu:
  734.             HandleRendererMenu( menuItem ) ;
  735.             break ;
  736.             
  737.         case mAppleMenu:
  738.             HandleAppleMenu( menuItem ) ;
  739.             break ;
  740.             
  741.         case mFileMenu:
  742.             HandleFileMenu( menuItem ) ;
  743.             break;
  744.         
  745.         case mEditMenu:
  746.             HandleEditMenu( menuItem ) ;
  747.             break ;
  748.             
  749.         case mViewMenu:
  750.             HandleViewMenu( menuItem ) ;
  751.             break ;
  752.  
  753.     }
  754.     HiliteMenu(0);        // Unhighlight whatever MenuSelect or MenuKey hilited
  755. }
  756.  
  757. /*------------------------------------------------------------*/
  758.  
  759. /*
  760. ** create a new viewer document window, this includes creating a
  761. ** document record, a window and an associated viewer object.  the
  762. ** document record is stored in the window's refcon field, so it
  763. ** can be accessed as required via the window record.
  764. */
  765.  
  766. WindowPtr DoCreateNewViewerWindow( unsigned char *windowName )
  767. {
  768.     WindowPtr            theWindow ;
  769.     Rect                myRect = { 0, 0, kWindHeight, kWindWidth } ;
  770.     TQ3ViewerObject        myViewer ;
  771.     ViewerDocumentHdl    myViewerDocument = NULL ;
  772.     
  773.     /* create a document record to hold the */
  774.     /* data for this instance */
  775.     myViewerDocument = (ViewerDocumentHdl)NewHandleClear(sizeof(ViewerDocument)) ;
  776.     
  777.     /* ideally we should stagger the rect */
  778.     OffsetRect( &myRect, 50, 50 ) ; 
  779.                       
  780.     theWindow = NewCWindow( NULL, 
  781.                          &myRect, 
  782.                          windowName, 
  783.                          true, 
  784.                          documentProc, 
  785.                          (WindowPtr)-1, 
  786.                          true, 
  787.                          0L ) ;
  788.                          
  789.     /* create the viewer object associated with this window */                   
  790.     if((myViewer = Q3ViewerNew( (CGrafPtr)theWindow, 
  791.                                 &theWindow->portRect, 
  792.                                 kQ3ViewerDefault )) != NULL) 
  793.     {
  794.         /* store a reference to the viewer in the document structure */
  795.         (**myViewerDocument).fViewer = myViewer ;
  796.         
  797.         /* store a reference to the document structure in the refcon */
  798.         /* field of the window */
  799.         SetWRefCon( theWindow, (long)myViewerDocument ) ;
  800.     }
  801.     else
  802.     {
  803.         /* clean up any allocates storage and quit */
  804.         if( myViewerDocument )
  805.             DisposeHandle( (Handle)myViewerDocument ) ;
  806.         
  807.         if( theWindow ) 
  808.             CloseWindow( theWindow ) ;
  809.         
  810.         theWindow = NULL ;
  811.     }
  812.     
  813.     return theWindow ;
  814.  
  815. }
  816.  
  817. /*------------------------------------------------------------*/
  818.  
  819. /*
  820. ** handle menu commands in the apple menu
  821. */
  822.  
  823.  
  824. void HandleAppleMenu( short menuItem )
  825. {
  826.     Str255        daName;
  827.     DialogPtr    theDialog ; 
  828.     short        itemHit ;
  829.     
  830.     switch ( menuItem ) {
  831.         ModalFilterUPP         theProc ;
  832.  
  833.         case iAppleAboutItem:
  834.             
  835.             theDialog = GetNewDialog ( kAboutDialogID, NULL, (WindowPtr)-1 );
  836.             
  837.             GetStdFilterProc( &theProc ) ;
  838.             SetDialogDefaultItem(theDialog, ok) ;
  839.             
  840.             
  841.             do {
  842.                 ModalDialog ( theProc, &itemHit );
  843.             } while( itemHit != ok ) ;
  844.             DisposDialog ( theDialog );
  845.             break;
  846.             
  847.         default:
  848.             GetItem(GetMHandle(mAppleMenu), menuItem, daName);
  849.             (void) OpenDeskAcc(daName);
  850.             break;
  851.     }
  852. }
  853.  
  854. /*------------------------------------------------------------*/
  855.  
  856. /*
  857. ** handle menu commands in the file menu
  858. */
  859.  
  860.  
  861. void HandleFileMenu( short menuItem )
  862. {
  863.     OSErr                theError ;
  864.     short                theRef ;
  865.     WindowPtr            theWindow ;
  866.     TQ3ViewerObject        theViewer ;
  867.     StandardFileReply    theSFReply ;
  868.     ViewerDocumentHdl    theViewerDocumentHdl ;
  869.     FSSpec                theFSSpec ;
  870.  
  871.     switch ( menuItem ) {
  872.     
  873.         case iFileNewItem:
  874.         
  875.             HandleFileNewItem( "\pViewer Window" ) ;
  876.             break ;
  877.     
  878.         case iFileSaveAsItem:
  879.         
  880.             if( (theWindow = FrontWindow()) != NULL )
  881.                 HandleFileSaveAsItem( theWindow ) ;
  882.             break ;
  883.  
  884.         case iFileSaveItem:
  885.             if( (theWindow = FrontWindow()) != NULL )
  886.                 HandleFileSaveItem( theWindow ) ;
  887.             break ;
  888.             
  889.         
  890.         case iFileRevertItem:
  891.             if( (theWindow = FrontWindow()) != NULL )
  892.                 HandleFileRevertItem( theWindow ) ;
  893.             break ;
  894.         
  895.         case iFilePageSetupItem:
  896.             if( (theWindow = FrontWindow()) != NULL )
  897.                 HandleFilePageSetupItem( theWindow ) ;
  898.             break ;
  899.         
  900.         case iFilePrintItem:
  901.             if( (theWindow = FrontWindow()) != NULL )
  902.                 HandleFilePrintItem( theWindow ) ;
  903.             break ;
  904.                 
  905.         case iFileOpenItem:
  906.         
  907.             /* Get the file name to open */
  908.             StandardGetFile( NULL, kNumTypes, kTypeList, &theSFReply ) ;
  909.     
  910.             /* did the user cancel? */
  911.             if(theSFReply.sfGood)
  912.                 HandleFileOpenItem( &theSFReply.sfFile ) ; /* no - process the file */
  913.                 
  914.             break ;
  915.             
  916.         case iFileCloseItem:
  917.             if( (theWindow = FrontWindow()) != NULL )
  918.                 HandleFileCloseItem( theWindow ) ;
  919.             break ;
  920.             
  921.         case iFileQuitItem:
  922.             HandleFileQuitItem();
  923.             break;
  924.     }
  925.  
  926. }
  927.  
  928. /*------------------------------------------------------------*/
  929.  
  930. /*
  931. ** handles the New menu item in the file menu
  932. */
  933.  
  934.  
  935. WindowPtr HandleFileNewItem( unsigned char *windowTitle )
  936. {
  937.     WindowPtr     theWindow ;    
  938.     theWindow = DoCreateNewViewerWindow( windowTitle ) ;
  939.     return theWindow ;
  940. }
  941.     
  942. /*------------------------------------------------------------*/
  943.  
  944. /*
  945. ** handles the Save As menu item in the file menu
  946. */
  947.  
  948.  
  949. OSErr HandleFileSaveAsItem( WindowPtr theWindow )
  950. {
  951.     OSErr                theError = paramErr ;
  952.     short                theRef ;
  953.  
  954.     TQ3ViewerObject        theViewer ;
  955.     StandardFileReply    theSFReply ;
  956.     ViewerDocumentHdl    theViewerDocumentHdl ;
  957.     FSSpec                theFSSpec ;
  958.  
  959.     /* this option can't be selected unless there is a frontwindow */
  960.     /* the option is dimmed in adjustmenus if there is no window */
  961.     if( theWindow != NULL ) /* sanity check */
  962.     {
  963.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  964.         if(theViewerDocumentHdl != NULL) 
  965.         {
  966.             StandardPutFile("\pSave model as:", "\pUntitled", &theSFReply);
  967.             if (theSFReply.sfGood)
  968.             {
  969.                 theError = FSpOpenDF(&theSFReply.sfFile, fsWrPerm, &theRef);
  970.                 if (theError != noErr)
  971.                 {
  972.                     theError = FSpCreate(&theSFReply.sfFile, '????', '3DMF', theSFReply.sfScript);
  973.                     if (theError == noErr)
  974.                         theError = FSpOpenDF(&theSFReply.sfFile, fsCurPerm, &theRef);
  975.                 }
  976.                 if (theError == noErr)
  977.                 {
  978.                     (**theViewerDocumentHdl).fFSSpec = theSFReply.sfFile ;
  979.                     theViewer= (**theViewerDocumentHdl).fViewer ;
  980.                     theError = Q3ViewerWriteFile(theViewer, (long)theRef);
  981.                     theError = FSClose(theRef);
  982.                 }
  983.                 
  984.                 /* reset the window title */
  985.                 SetWTitle( theWindow, theSFReply.sfFile.name );
  986.             }                    
  987.         }
  988.     }
  989.     return theError ;
  990. }
  991.  
  992. /*------------------------------------------------------------*/
  993.  
  994. /*
  995. ** handles the Save menu item in the file menu
  996. */
  997.  
  998.  
  999. OSErr HandleFileSaveItem( WindowPtr theWindow )
  1000. {
  1001.     OSErr                theError = paramErr ;
  1002.     short                theRef ;
  1003.  
  1004.     TQ3ViewerObject        theViewer ;
  1005.     StandardFileReply    theSFReply ;
  1006.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1007.     FSSpec                theFSSpec ;
  1008.  
  1009.     /* this option can't be selected unless there is a frontwindow */
  1010.     /* the option is dimmed in adjustmenus if there is no window */
  1011.     if( theWindow != NULL )        /* sanity check */
  1012.     {
  1013.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1014.         if(theViewerDocumentHdl != NULL) 
  1015.         {
  1016.             theFSSpec = (**theViewerDocumentHdl).fFSSpec ;
  1017.             
  1018.             /* open the file */
  1019.             theError = FSpOpenDF ( &theFSSpec, fsWrPerm, &theRef ) ;
  1020.             if( theError == noErr ) 
  1021.             {
  1022.                 if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  1023.                 {
  1024.                     theError = Q3ViewerWriteFile( theViewer, (long)theRef );
  1025.                     if( theError == noErr )
  1026.                         theError = FSClose ( theRef ) ;
  1027.                 }
  1028.             }
  1029.         }
  1030.     }
  1031.     return theError ;
  1032.             
  1033. }
  1034.         
  1035. /*------------------------------------------------------------*/
  1036.  
  1037. /*
  1038. ** handles the Revert menu item in the file menu
  1039. */
  1040.  
  1041.  
  1042. OSErr HandleFileRevertItem( WindowPtr theWindow )
  1043. {
  1044.     OSErr                theError = paramErr ;
  1045.     short                theRef ;
  1046.  
  1047.     TQ3ViewerObject        theViewer ;
  1048.     StandardFileReply    theSFReply ;
  1049.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1050.     FSSpec                theFSSpec ;
  1051.  
  1052.     /* this option can't be selected unless there is a frontwindow */
  1053.     /* the option is dimmed in adjustmenus if there is no window */
  1054.     if( theWindow != NULL )        /* sanity check */
  1055.     {
  1056.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1057.         if(theViewerDocumentHdl != NULL) 
  1058.         {
  1059.             theFSSpec = (**theViewerDocumentHdl).fFSSpec ;
  1060.             
  1061.             /* open the file */
  1062.             theError = FSpOpenDF ( &theFSSpec, fsRdPerm, &theRef ) ;
  1063.             if( theError == noErr ) 
  1064.             {
  1065.                 if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  1066.                 {
  1067.                 //    Q3ViewerClear( theViewer ) ;
  1068.                     theError = Q3ViewerUseFile( theViewer, (long)theRef );
  1069.                     if( theError == noErr )
  1070.                         theError = FSClose ( theRef ) ;
  1071.                 }
  1072.             }
  1073.         }
  1074.     }
  1075.     Q3ViewerDraw( theViewer )  ;
  1076.     return theError ;
  1077. }
  1078.  
  1079. /*------------------------------------------------------------*/
  1080.  
  1081. /*
  1082. ** handles the Page Setup menu item in the file menu
  1083. */
  1084.  
  1085.  
  1086. OSErr HandleFilePageSetupItem( WindowPtr theWindow )
  1087. {
  1088.     return noErr ;
  1089. }
  1090.  
  1091. /*------------------------------------------------------------*/
  1092.  
  1093. /*
  1094. ** handles the Print menu item in the file menu
  1095. */
  1096.  
  1097.  
  1098. OSErr HandleFilePrintItem( WindowPtr theWindow )
  1099. {
  1100.     return noErr ;
  1101. }    
  1102.     
  1103. WindowPtr HandleFileOpenItem( FSSpec *theFSSpec )
  1104. {
  1105.     OSErr                theError ;
  1106.     short                theRef ;
  1107.     WindowPtr            theWindow ;
  1108.     TQ3ViewerObject        theViewer ;
  1109.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1110.  
  1111.     /* open the file */
  1112.     theError = FSpOpenDF( theFSSpec, fsRdPerm, &theRef ) ;
  1113.     
  1114.     if( theError == noErr )
  1115.     {                    
  1116.         theWindow = DoCreateNewViewerWindow( theFSSpec->name) ;
  1117.         
  1118.         if( theWindow != NULL )
  1119.         {
  1120.             
  1121.             theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1122.             if(theViewerDocumentHdl != NULL) 
  1123.             {
  1124.                 if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  1125.                 {
  1126.                     (**theViewerDocumentHdl).fFSSpec = *theFSSpec ;
  1127.                     theError = Q3ViewerUseFile( theViewer, theRef );
  1128.                     if( theError == noErr )
  1129.                         theError = FSClose ( theRef ) ;
  1130.                 }
  1131.             }
  1132.         }
  1133.     }
  1134.     return theWindow ;
  1135. }    
  1136.         
  1137. /*------------------------------------------------------------*/
  1138.  
  1139. /*
  1140. ** handles the close menu item in the file menu
  1141. ** close the window after disposing of the associated
  1142. ** data structures (viewer, etc).
  1143. */
  1144.  
  1145.  
  1146. OSErr HandleFileCloseItem( WindowPtr theWindow )
  1147. {
  1148.  
  1149.     OSErr                theError = paramErr ;
  1150.     short                theRef ;
  1151.  
  1152.     TQ3ViewerObject        theViewer ;
  1153.     StandardFileReply    theSFReply ;
  1154.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1155.     FSSpec                theFSSpec ;
  1156.  
  1157.     /* this option can't be selected unless there is a frontwindow */
  1158.     /* the option is dimmed in adjustmenus if there is no window */
  1159.     if( theWindow != NULL )        /* sanity check */
  1160.     {
  1161.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1162.         if(theViewerDocumentHdl != NULL) 
  1163.         {
  1164.             if((theViewer = (**theViewerDocumentHdl).fViewer) != NULL) 
  1165.             {
  1166.                 theError = Q3ViewerDispose( theViewer ) ;
  1167.                 if( theError == noErr )
  1168.                     DisposeWindow( theWindow ) ;
  1169.             }
  1170.         }
  1171.     }
  1172.     return theError ;
  1173.             
  1174. }
  1175.  
  1176. /*
  1177. ** handles the Quit menu item in the file menu
  1178. */
  1179.  
  1180. OSErr HandleFileQuitItem( void ) 
  1181. {
  1182.     OSErr             theError = noErr ;        /* this is used as the return value */
  1183.     WindowPtr        theWindow ;
  1184.     Boolean            tempQuitFlag = true ;
  1185.  
  1186.     /*
  1187.     ** if the application has any open windows, close them before 
  1188.     ** tempQuitFlag.  Since the user may cancelduring the process of 
  1189.     ** closing, make sure we don't quit the app, unless they can 
  1190.     ** be closed
  1191.     */
  1192.     while(( theWindow = FrontWindow()) != NULL && tempQuitFlag )
  1193.         tempQuitFlag = ( HandleFileCloseItem( theWindow ) == noErr) ;    
  1194.         
  1195.  
  1196.     /*
  1197.     ** if we closed everything up successfully, return noErr, otherwise
  1198.     ** indicate to the caller of this function that we canceled
  1199.     */
  1200.     
  1201.     if (tempQuitFlag) {
  1202.         gQuitFlag = true;                    /* in other word the user didn't cancel */
  1203.          AEDisposeDesc(&gSelfAddress);        /* don't forget to dispose of the       */
  1204.                                              /* self-addressed descriptor.            */
  1205.     }
  1206.     else {
  1207.         theError = userCanceledErr ;
  1208.     }
  1209.     
  1210.     return theError ;
  1211.  
  1212. }
  1213.  
  1214. /*------------------------------------------------------------*/
  1215.  
  1216. /*
  1217. ** handle menu commands in the edit menu
  1218. */
  1219.  
  1220.  
  1221. void HandleEditMenu( short menuItem )
  1222. {
  1223.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1224.     WindowPtr            theWindow ;
  1225.     TQ3ViewerObject        theViewer ;
  1226.     OSErr                theError ;
  1227.     theWindow = FrontWindow() ;
  1228.     
  1229.     if( theWindow != NULL )
  1230.     {
  1231.         /*
  1232.         ** get the reference to our viewer document data structure
  1233.         ** from the long reference constant for the window.  Cast
  1234.         ** it to the appropriate type.  If we can't get it (i.e. it's
  1235.         ** null we want to bail
  1236.         */
  1237.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1238.         if(theViewerDocumentHdl == NULL) 
  1239.             return ;
  1240.             
  1241.         /* get the reference to the viewer object from our data structure */    
  1242.         theViewer = (**theViewerDocumentHdl).fViewer ;
  1243.         if(theViewer == NULL) 
  1244.             return ;
  1245.         
  1246.         switch ( menuItem ) 
  1247.         {
  1248.             
  1249.             case iEditUndoItem:
  1250.                 /* we don't really support undo in this app */
  1251.                 break ;
  1252.                 
  1253.             case iEditCutItem:
  1254.                 theError = Q3ViewerCut ( theViewer ) ;
  1255.                 break ;
  1256.                 
  1257.             case iEditCopyItem:
  1258.                 theError = Q3ViewerCopy ( theViewer ) ;
  1259.                 break ;
  1260.                 
  1261.             case iEditPasteItem:
  1262.                 theError = Q3ViewerPaste ( theViewer ) ;
  1263.                 break ;
  1264.                 
  1265.             case iEditClearItem:
  1266.                 theError = Q3ViewerClear ( theViewer ) ;    
  1267.                 break ;        
  1268.         }
  1269.     }
  1270.  
  1271. }
  1272.  
  1273. /*------------------------------------------------------------*/
  1274.  
  1275. /*
  1276. ** handle menu commands in the renderer menu
  1277. */
  1278.  
  1279.  
  1280. void HandleRendererMenu( short menuItem )
  1281. {
  1282.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1283.     WindowPtr            theWindow ;
  1284.     TQ3ViewerObject        theViewer ;
  1285.     OSErr                theError ;
  1286.     TQ3ViewObject         myView ;
  1287.     TQ3Status            myStatus ;
  1288.     TQ3RendererObject    myRenderer ;
  1289.     
  1290.     theWindow = FrontWindow() ;
  1291.  
  1292.  
  1293.     
  1294.     if( theWindow != NULL )
  1295.     {
  1296.         /*
  1297.         ** get the reference to our viewer document data structure
  1298.         ** from the long reference constant for the window.  Cast
  1299.         ** it to the appropriate type.  If we can't get it (i.e. it's
  1300.         ** null we want to bail
  1301.         */
  1302.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1303.         if(theViewerDocumentHdl == NULL) 
  1304.             return ;
  1305.  
  1306.         /* get the reference to the viewer object from our data structure */    
  1307.         theViewer = (**theViewerDocumentHdl).fViewer ;
  1308.         if(theViewer == NULL) 
  1309.             return ;
  1310.         
  1311.         switch ( menuItem ) 
  1312.         {
  1313.             
  1314.             /*
  1315.             ** These two items are contained in the Renderer
  1316.             ** sub-menu from the view menu
  1317.             */
  1318.             case iRendererWireframeItem:
  1319.                 /* get an instance to a wireframe renderer object */
  1320.                 myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  1321.                 break ;
  1322.                 
  1323.             case iRendererInteractiveItem:
  1324.                 /* get an instance to a interactive renderer object */
  1325.                 myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive);
  1326.                 break ;
  1327.                 
  1328.             default:
  1329.                 /*
  1330.                 ** if we got here there is something very wrong, 
  1331.                 ** so we'll just return
  1332.                 */
  1333.                 return ;
  1334.                 
  1335.         }
  1336.         /*
  1337.         ** set the renderer for the view
  1338.         */
  1339.         myView = Q3ViewerGetView( theViewer );
  1340.         if( myView != NULL )
  1341.         {
  1342.             /* set the renderer to the one created in the switch statement above */
  1343.             myStatus = Q3View_SetRenderer(myView, myRenderer) ;
  1344.             
  1345.             /* now we have set the renderer we can dispose of the reference to it */
  1346.             myStatus = Q3Object_Dispose( myRenderer ) ;
  1347.             
  1348.             /* and redraw the content region of the viewer */
  1349.             theError = Q3ViewerDraw( theViewer ) ;
  1350.         }
  1351.     }
  1352. }
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359. /*------------------------------------------------------------*/
  1360.  
  1361. /*
  1362. ** handle menu commands in the view menu
  1363. */
  1364.  
  1365.  
  1366. void HandleViewMenu( short menuItem )
  1367. {
  1368.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1369.     WindowPtr            theWindow ;
  1370.     TQ3ViewerObject        theViewer ;
  1371.     OSErr                theError ;
  1372.     unsigned long        theViewerFlags;
  1373.     Rect                theTmpRect ;
  1374.     GrafPtr                savedPort ;
  1375.     RGBColor            theRGBColor ;
  1376.     TQ3ColorARGB        theViewerBGColor;
  1377.  
  1378.     theWindow = FrontWindow() ;
  1379.     
  1380.     if( theWindow != NULL )
  1381.     {
  1382.         /*
  1383.         ** get the reference to our viewer document data structure
  1384.         ** from the long reference constant for the window.  Cast
  1385.         ** it to the appropriate type.  If we can't get it (i.e. it's
  1386.         ** null we want to bail
  1387.         */
  1388.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1389.         if(theViewerDocumentHdl == NULL) 
  1390.             return ;
  1391.         
  1392.         /* get the reference to the viewer object from our data structure */    
  1393.         theViewer = (**theViewerDocumentHdl).fViewer ;
  1394.         if(theViewer == NULL) 
  1395.             return ;
  1396.         
  1397.         /*
  1398.         ** since most of the items in this menu rely on adjusting
  1399.         ** the viewer flags, we'll get the flags here so we can
  1400.         ** bitwise manipulate them in the switch below
  1401.         */ 
  1402.         theViewerFlags = Q3ViewerGetFlags( theViewer ) ;
  1403.     
  1404.         switch ( menuItem ) 
  1405.         {
  1406.             /*
  1407.             ** the renderer item in this menu is handled
  1408.             ** by handlers for it's repective hierarchical        
  1409.             ** menus, so we just need to handle the ones below
  1410.             */    
  1411.             
  1412.             case iViewBadgeItem:
  1413.                 /* 
  1414.                 ** this toggles the viewer bage and hides the
  1415.                 ** vcontroller, clicking in the badge will
  1416.                 ** hide the badge and show the controller
  1417.                 */
  1418.                 theViewerFlags ^= kQ3ViewerShowBadge;
  1419.                 theViewerFlags ^= kQ3ViewerControllerVisible;
  1420.                 break ;
  1421.                 
  1422.             case iViewCameraButtonItem:
  1423.                 theViewerFlags ^= kQ3ViewerButtonCamera ;
  1424.                 break ;
  1425.                 
  1426.             case iViewTruckButtonItem:
  1427.                 theViewerFlags ^= kQ3ViewerButtonTruck ;
  1428.                 break ;
  1429.                 
  1430.             case iViewOrbitButtonItem:
  1431.                 theViewerFlags ^= kQ3ViewerButtonOrbit ;
  1432.                 break ;
  1433.                 
  1434.             case iViewZoomButtonItem:
  1435.                 theViewerFlags ^= kQ3ViewerButtonZoom ;
  1436.                 break ;
  1437.                 
  1438.             case iViewDollyButtonItem:
  1439.                 theViewerFlags ^= kQ3ViewerButtonDolly ;
  1440.                 break ;
  1441.                 
  1442.             case iViewInsetNFrameItem:
  1443.                 /*
  1444.                 ** this toggles drawing the viewer slightly smaller 
  1445.                 **than the window.  We key off the kQ3ViewerDrawFrame
  1446.                 ** viewer flag - if it is set then we are already inset
  1447.                 */
  1448.                 theTmpRect = theWindow->portRect ;
  1449.                 if( theViewerFlags & kQ3ViewerDrawFrame ) 
  1450.                 {
  1451.                     Q3ViewerSetBounds( theViewer, &theTmpRect ) ;
  1452.                 }
  1453.                 else
  1454.                 {
  1455.                     InsetRect( &theTmpRect, kInsetPixelsConst, kInsetPixelsConst ) ;
  1456.                     Q3ViewerSetBounds( theViewer, &theTmpRect ) ;
  1457.                 }
  1458.                 theViewerFlags ^= kQ3ViewerDrawFrame ;
  1459.                 
  1460.                 GetPort( &savedPort ) ;
  1461.                 SetPort( (GrafPtr)theWindow ) ;
  1462.                 EraseRect( &theWindow->portRect ) ;
  1463.                 SetPort( savedPort ) ;
  1464.                 
  1465.                 break ;
  1466.             
  1467.             case iViewSetBackgroundColorItem:
  1468.     
  1469.                 Q3ViewerGetBackgroundColor(theViewer, &theViewerBGColor);
  1470.                 theRGBColor.red = theViewerBGColor.r * 65535.0;
  1471.                 theRGBColor.green = theViewerBGColor.g * 65535.0;
  1472.                 theRGBColor.blue = theViewerBGColor.b * 65535.0;
  1473.                 
  1474.                 if(PickViewerBackGroundColor( &theRGBColor, "\pPick a viewer background color:" ))
  1475.                 {
  1476.                     theViewerBGColor.a = 1;
  1477.                     theViewerBGColor.r = theRGBColor.red / 65535.0;
  1478.                     theViewerBGColor.g = theRGBColor.green / 65535.0;
  1479.                     theViewerBGColor.b = theRGBColor.blue / 65535.0;
  1480.                     Q3ViewerSetBackgroundColor(theViewer, &theViewerBGColor);
  1481.                 }
  1482.                 break;                                
  1483.         }
  1484.     }
  1485.     Q3ViewerSetFlags( theViewer, theViewerFlags ) ;
  1486.     Q3ViewerDraw( theViewer ) ;
  1487.  
  1488. }
  1489.  
  1490. Boolean PickViewerBackGroundColor(RGBColor *theRGBColor, unsigned char *thePrompt )
  1491. {
  1492.     ColorPickerInfo        cpInfo;
  1493.     Boolean                returnValue = false ;
  1494.     
  1495.     /* setting input color to be an RGB color */
  1496.     cpInfo.theColor.color.rgb.red = (*theRGBColor).red;
  1497.     cpInfo.theColor.color.rgb.blue = (*theRGBColor).blue;
  1498.     cpInfo.theColor.color.rgb.green = (*theRGBColor).green;
  1499.     
  1500.     cpInfo.theColor.profile = 0L;
  1501.     
  1502.     /* no colorsync destination profile */
  1503.     cpInfo.dstProfile = 0L;
  1504.     
  1505.     /* set the color picker flags */
  1506.     cpInfo.flags = AppIsColorSyncAware | CanModifyPalette | 
  1507.                         CanAnimatePalette;
  1508.                         
  1509.     /* center dialog box on the deepest color screen */
  1510.     cpInfo.placeWhere = kDeepestColorScreen;
  1511.     
  1512.     /* use the system default picker */
  1513.     cpInfo.pickerType = 0L;
  1514.     
  1515.     /* install event filter and color-changed functions */
  1516.     cpInfo.eventProc = nil;            
  1517.     cpInfo.colorProc = nil;
  1518.     cpInfo.colorProcData = 0L;
  1519.     
  1520.     /* sanity check */
  1521.     if( thePrompt[ 0 ] >= 255 )
  1522.         if( thePrompt[ 0 ] = 255 ) ;
  1523.         
  1524.     BlockMove( thePrompt, cpInfo.prompt, thePrompt[0] ) ;
  1525.     
  1526.     /* describe the Edit menu for Color Picker Manager */
  1527.     cpInfo.mInfo.editMenuID = mEditMenu ;
  1528.     cpInfo.mInfo.cutItem     = iEditCutItem;
  1529.     cpInfo.mInfo.copyItem     = iEditCopyItem;
  1530.     cpInfo.mInfo.pasteItem    = iEditPasteItem;
  1531.     cpInfo.mInfo.clearItem     = iEditClearItem;
  1532.     cpInfo.mInfo.undoItem     = iEditUndoItem;
  1533.  
  1534.     /* display dialog box to allow user to choose a color */
  1535.     if(PickColor(&cpInfo) == noErr && cpInfo.newColorChosen)
  1536.     {
  1537.         /* use this new color */
  1538.         (*theRGBColor).red = cpInfo.theColor.color.rgb.red ;
  1539.         (*theRGBColor).blue = cpInfo.theColor.color.rgb.blue ;
  1540.         (*theRGBColor).green = cpInfo.theColor.color.rgb.green ;
  1541.         
  1542.         /* set up the return value */
  1543.         returnValue = cpInfo.newColorChosen ;
  1544.     }
  1545.         
  1546.     return returnValue ;
  1547. }
  1548.  
  1549.  
  1550. /*------------------------------------------------------------*/
  1551.  
  1552. /*
  1553. ** make sure that menus are enabled and disabled in an
  1554. ** appropriate manner
  1555. */
  1556.  
  1557.  
  1558. void AdjustMenus( void ) 
  1559. {
  1560.     MenuHandle            theMenu ;
  1561.     ViewerDocumentHdl    theViewerDocumentHdl ;
  1562.     WindowPtr            theWindow ;
  1563.     TQ3ViewerObject        theViewer ;
  1564.     TQ3ViewObject         myView ;
  1565.     TQ3Status            myStatus ;
  1566.     TQ3RendererObject    myRenderer ;
  1567.     TQ3ObjectType        theRendererType ;
  1568.     OSErr                theError ;
  1569.     Rect                theTmpRect ;
  1570.     GrafPtr                savedPort ;
  1571.     long                tmpLong, theScrapOffset ;
  1572.     unsigned long        theViewerFlags;
  1573.     unsigned long        theViewerState ;
  1574.  
  1575.     theWindow = FrontWindow() ;
  1576.     
  1577.     
  1578.     /* do we have a viewer theWindow open */
  1579.     if( theWindow != NULL ) {
  1580.         
  1581.         /* there is a theWindow, enable our menu commands */
  1582.  
  1583.         /*
  1584.         ** get the reference to our viewer document data structure
  1585.         ** from the long reference constant for the window.  Cast
  1586.         ** it to the appropriate type.  If we can't get it (i.e. it's
  1587.         ** null we want to bail
  1588.         */
  1589.         theViewerDocumentHdl = (ViewerDocumentHdl)GetWRefCon(theWindow) ;
  1590.         if(theViewerDocumentHdl == NULL) 
  1591.             return ;
  1592.         
  1593.         /* get the reference to the viewer object from our data structure */    
  1594.         theViewer = (**theViewerDocumentHdl).fViewer ;
  1595.         if(theViewer == NULL) 
  1596.             return ;
  1597.             
  1598.         /* get the viewer state, we need to know if it is empty */    
  1599.         theViewerState = Q3ViewerGetState( theViewer ) ;
  1600.         
  1601.         /* adjust the file menu */
  1602.         theMenu = GetMHandle ( mFileMenu ) ;
  1603.         
  1604.         EnableItem ( theMenu, iFileNewItem );        /* always enabled */
  1605.         EnableItem ( theMenu, iFileOpenItem );        /* always enabled */
  1606.         EnableItem ( theMenu, iFileQuitItem );        /* always enabled */
  1607.  
  1608.         EnableItem ( theMenu, iFileCloseItem );
  1609.         
  1610.         if( ((theViewerState & kQ3ViewerHasModel) ? true : false ) ) 
  1611.         {
  1612.             EnableItem ( theMenu, iFileSaveItem );
  1613.             EnableItem ( theMenu, iFileSaveAsItem );
  1614.             EnableItem ( theMenu, iFileRevertItem );
  1615.             EnableItem ( theMenu, iFilePageSetupItem );
  1616.             EnableItem ( theMenu, iFilePrintItem );
  1617.         }
  1618.         else
  1619.         {
  1620.             DisableItem ( theMenu, iFileSaveItem );
  1621.             DisableItem ( theMenu, iFileSaveAsItem );
  1622.             DisableItem ( theMenu, iFileRevertItem );
  1623.             DisableItem ( theMenu, iFilePageSetupItem );
  1624.             DisableItem ( theMenu, iFilePrintItem );
  1625.         }
  1626.         
  1627.         
  1628.         /* adjust the edit menu */
  1629.         theMenu = GetMHandle ( mEditMenu ) ;
  1630.         
  1631.         DisableItem ( theMenu, iEditUndoItem );    /* always disabled, no undo support in this app */
  1632.  
  1633.  
  1634.         if( ((theViewerState & kQ3ViewerHasModel) ? true : false ) ) 
  1635.         {
  1636.             EnableItem ( theMenu, iEditCutItem );
  1637.             EnableItem ( theMenu, iEditCopyItem );
  1638.             EnableItem ( theMenu, iEditClearItem );
  1639.         }
  1640.         else
  1641.         {
  1642.             DisableItem ( theMenu, iEditCutItem );
  1643.             DisableItem ( theMenu, iEditCopyItem );
  1644.             DisableItem ( theMenu, iEditClearItem );
  1645.         }
  1646.         
  1647.         /*
  1648.         ** check that there is some data that we can paste.  GetScrap returns
  1649.         ** a long that gives either the length of the requested type, or a
  1650.         ** negative error code that is used to indicate that no such type exists
  1651.         */
  1652.         
  1653.         tmpLong = GetScrap( nil, '3DMF', &theScrapOffset ) ;
  1654.         if( tmpLong < 0 )
  1655.             DisableItem ( theMenu, iEditPasteItem );
  1656.         else
  1657.             EnableItem ( theMenu, iEditPasteItem );
  1658.             
  1659.  
  1660.         
  1661.         /* adjust the view menu */
  1662.         theMenu = GetMHandle ( mViewMenu ) ;
  1663.         EnableItem ( theMenu, 0L );
  1664.         
  1665.         /*
  1666.         ** since most of the items in this menu rely on adjusting
  1667.         ** the viewer flags, we'll get the flags here so we can
  1668.         ** bitwise manipulate them in the switch below
  1669.         */ 
  1670.         theViewerFlags = Q3ViewerGetFlags( theViewer ) ;
  1671.         
  1672.         /*
  1673.         ** check each of the items that have their flag
  1674.         ** bits set to true in the viewer flags.
  1675.         **
  1676.         ** Note that the Boolean flag for CheckItem is defined
  1677.         ** (( theViewerFlags & kQ3ViewerShowBadge ) ? true : false)
  1678.         ** and so on.  The reson for this is that simply adding
  1679.         ** ( theViewerFlags & kQ3ViewerShowBadge ) won't be sufficient
  1680.         ** if the flag is the 8th bit or more of the unsigned long 
  1681.         ** defined to hold the flages, since the param passed will 
  1682.         ** only be the first 8 bits (of couse this is dependent on
  1683.         ** the develolment system size for Boolean, but this is true
  1684.         ** for CodeWarrior.
  1685.         */
  1686.         
  1687.         CheckItem( theMenu, iViewBadgeItem, (( theViewerFlags & kQ3ViewerShowBadge ) ? true : false)) ;
  1688.         CheckItem( theMenu, iViewCameraButtonItem, (( theViewerFlags & kQ3ViewerButtonCamera ) ? true : false)) ;
  1689.         CheckItem( theMenu, iViewTruckButtonItem, (( theViewerFlags & kQ3ViewerButtonTruck ) ? true : false)) ;
  1690.         CheckItem( theMenu, iViewOrbitButtonItem, (( theViewerFlags & kQ3ViewerButtonOrbit ) ? true : false)) ;
  1691.         CheckItem( theMenu, iViewZoomButtonItem, (( theViewerFlags & kQ3ViewerButtonZoom ) ? true : false)) ;
  1692.         CheckItem( theMenu, iViewDollyButtonItem, (( theViewerFlags & kQ3ViewerButtonDolly ) ? true : false)) ;
  1693.         CheckItem( theMenu, iViewInsetNFrameItem, (( theViewerFlags & kQ3ViewerDrawFrame ) ? true : false)) ;
  1694.         
  1695.         /* adjust the renderer menu */
  1696.         theMenu = GetMHandle ( mRendererMenu ) ;
  1697.         
  1698.         /*
  1699.         ** get the renderer for the view
  1700.         */
  1701.         myView = Q3ViewerGetView( theViewer );
  1702.         if( myView != NULL )
  1703.         {
  1704.             /* set the renderer to the one created in the switch statement above */
  1705.             myStatus = Q3View_GetRenderer(myView, &myRenderer) ;
  1706.             theRendererType = Q3Renderer_GetType( myRenderer ) ;
  1707.  
  1708.             CheckItem( theMenu, iRendererInteractiveItem, (theRendererType == kQ3RendererTypeInteractive)) ;
  1709.             CheckItem( theMenu, iRendererWireframeItem,  (theRendererType == kQ3RendererTypeWireFrame)) ;
  1710.  
  1711.             /* 
  1712.             ** getting the renderer incremented the ref count for it,
  1713.             ** we can dispose of the reference to it 
  1714.             */
  1715.             myStatus = Q3Object_Dispose( myRenderer ) ;
  1716.             
  1717.         }
  1718.         
  1719.  
  1720.     }
  1721.     else {
  1722.     
  1723.         /* there is NOT a front window, disable most of our menu commands */
  1724.     
  1725.         /* adjust the file menu */
  1726.         theMenu = GetMHandle ( mFileMenu ) ;
  1727.         
  1728.         EnableItem ( theMenu, iFileNewItem );        /* always enabled */
  1729.         EnableItem ( theMenu, iFileOpenItem );        /* always enabled */
  1730.         EnableItem ( theMenu, iFileQuitItem );        /* always enabled */
  1731.  
  1732.         DisableItem ( theMenu, iFileCloseItem );
  1733.         DisableItem ( theMenu, iFileSaveItem );
  1734.         DisableItem ( theMenu, iFileSaveAsItem );
  1735.         DisableItem ( theMenu, iFileRevertItem );
  1736.         DisableItem ( theMenu, iFilePageSetupItem );
  1737.         DisableItem ( theMenu, iFilePrintItem );
  1738.  
  1739.         /* adjust the edit menu */
  1740.         theMenu = GetMHandle ( mEditMenu ) ;
  1741.         
  1742.         DisableItem ( theMenu, iEditUndoItem );    /* always disabled, no undo support in this app */
  1743.         DisableItem ( theMenu, iEditCutItem );
  1744.         DisableItem ( theMenu, iEditCopyItem );
  1745.         DisableItem ( theMenu, iEditPasteItem );
  1746.         DisableItem ( theMenu, iEditClearItem );
  1747.         
  1748.         /* disable the entire view menu if there is no window */
  1749.         theMenu = GetMHandle ( mViewMenu ) ;
  1750.         DisableItem ( theMenu, 0L );
  1751.  
  1752.     }
  1753.     DrawMenuBar() ;
  1754. }
  1755.  
  1756.  
  1757.